// dllmain.cpp : 定义 DLL 应用程序的入口点。
#pragma once
#include "hwd.h"
#include "comm.h"
#include "km.h"
#include "api.h"
#include "dwmDraw.hpp"
#include <CommCtrl.h>

ULONG64 g人物基址 = 0x149D3AA48;
ULONG64 g技能栏位 = 0x11230;
ULONG64 g技能判断 = 0x10510;
ULONG64 g技能偏移 = 0xD0;
ULONG64 g技能名称 = 0xB8;
ULONG64 g技能代码 = 0xB0;
ULONG64 g技能等级 = 0x1B20;
ULONG64 g技能上限等级 = 0x380;
ULONG64 g转职判断 = 0x149DA7804;
ULONG64 g技能冷却 = 0xB40;
ULONG64 g密钥常量 = 522846812;
ULONG64 g技能属性 = 0x12A8;

#define dcr(v) ((v ^ g密钥常量) - 4)
#define cr(v) ((v + 4) ^ g密钥常量)

void ChangeSkill(ULONG64 pid,const char * 待修改的技能名,int 属性位,float 待修改属性值,int 无CD,int 满级) {

	ULONG64 人物指针 = 0;
	ULONG64 技能指针 = 0;
	ULONG32 技能判断 = 0;
	ULONG64 技能开始 = 0;
	ULONG64 技能结束 = 0;

	Api_ReadProcMemory(pid, g人物基址, (ULONG64)(&人物指针), 8, 0);//取人物指针
	Api_ReadProcMemory(pid, 人物指针 + g技能栏位, (ULONG64)(&技能指针), 8, 0);//取技能指针
	Api_ReadProcMemory(pid, 人物指针 + g技能判断, (ULONG64)(&技能判断), 4, 0);//取技能判断
	Api_ReadProcMemory(pid, 技能指针 + 技能判断 * 40 + g技能偏移, (ULONG64)(&技能开始), 8, 0);//取技能开始
	Api_ReadProcMemory(pid, 技能指针 + 技能判断 * 40 + g技能偏移 + 8, (ULONG64)(&技能结束), 8, 0);//取技能结束

	for (ULONG64 i = 0; i < (技能结束 - 技能开始) / 8; i++)
	{
		技能指针 = 0;
		Api_ReadProcMemory(pid, 技能开始 + i * 8, (ULONG64)(&技能指针), 8, 0);

		if (!技能指针)
		{
			continue;
		}

		ULONG64 temp = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能名称, (ULONG64)(&temp), 8, 0);

		//取技能名
		char arr[250] = { 0 };
		Api_ReadProcMemory(pid, temp, (ULONG64)(&(arr[0])), 250, 0);
		char 技能名称[250] = { 0 };
		WideCharToMultiByte(CP_ACP, 0, (LPWSTR)arr, 250 / 2, 技能名称, 250 / 2, 0, 0);

		if (strcmp(待修改的技能名, 技能名称)!=0)
		{
			continue;
		}
		//技能代码
		//ULONG64 skillcode = 0;
		//Api_ReadProcMemory(pid, 技能指针 + g技能代码, (ULONG64)(&skillcode), 8, 0);
		//skillcode ^= g密钥常量;
		//skillcode -= 4;

		//当前技能等级
		ULONG64 skilllevel = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能等级, (ULONG64)(&skilllevel), 8, 0);
		skilllevel ^= g密钥常量;
		skilllevel -= 4;

		//技能精通等级
		ULONG64 maxlevel = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能上限等级, (ULONG64)(&maxlevel), 8, 0);
		maxlevel ^= g密钥常量;
		maxlevel -= 4;

		//修改技能等级为精通等级
		if (满级)
		{
			skilllevel = maxlevel;
			skilllevel += 4;
			skilllevel ^= g密钥常量;
			Api_WriteProcMemory(pid, 技能指针 + g技能等级, (ULONG64)(&skilllevel), 8, 0);
			Api_WriteProcMemory(pid, 技能指针 + g技能等级 - 8, (ULONG64)(&skilllevel), 8, 0);
		}
		else
		{
			maxlevel = skilllevel;
		}
		

		ULONG32 专职判断 = 0;
		Api_ReadProcMemory(pid, g转职判断, (ULONG64)(&专职判断), 4, 0);

		ULONG64 temptemp = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能冷却 + 专职判断 * 32, (ULONG64)(&temptemp), 8, 0);
		temptemp += ((ULONG32)(maxlevel)) * 8 - 8;

		ULONG64 skillcd = 0;
		Api_ReadProcMemory(pid, temptemp, (ULONG64)(&skillcd), 8, 0);
		skillcd ^= g密钥常量;
		skillcd -= 4;

		if (无CD)
		{
			skillcd = 0;
			skillcd += 4;
			skillcd ^= g密钥常量;
			Api_WriteProcMemory(pid, temptemp, (ULONG64)(&skillcd), 8, 0);
		}
		


		ULONG64 属性数量 = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能属性 + 8, (ULONG64)(&属性数量), 8, 0);

		if (属性位>= 属性数量)
		{
			return;
		}
		ULONG64 属性指针 = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能属性, (ULONG64)(&属性指针), 8, 0);

		ULONG64 当前指针 = 0;
		ULONG64 找到指针 = 0;
		Api_ReadProcMemory(pid, 属性指针 + 8, (ULONG64)(&当前指针), 8, 0);
		UCHAR sign = 1;
		Api_ReadProcMemory(pid, 当前指针 + 71, (ULONG64)(&sign), 1, 0);
		while (sign == 0)
		{
			ULONG32 当前编号 = 0;
			Api_ReadProcMemory(pid, 当前指针 + 32, (ULONG64)(&当前编号), 4, 0);
			if (当前编号 == 属性位)
			{
				找到指针 = 当前指针;
				break;
			}
			if (当前编号 > 属性位)
			{
				Api_ReadProcMemory(pid, 当前指针, (ULONG64)(&当前指针), 8, 0);
			}
			else {
				Api_ReadProcMemory(pid, 当前指针 + 8 * 2, (ULONG64)(&当前指针), 8, 0);
			}
		}
		if (找到指针 == 0)
		{
			return;
		}

		Api_ReadProcMemory(pid, 找到指针 + 48, (ULONG64)(&找到指针), 8, 0);
		找到指针 += ((ULONG32)(maxlevel)) * 8 - 8;

		ULONG32 属性值 = 0;
		//Api_ReadProcMemory(pid, 找到指针, (ULONG64)(&属性值), 4, 0);
		//属性值 ^= g密钥常量;
		//属性值 -= 4;
		//float ffff = *(float*)(&属性值);


		float ffff = 待修改属性值;
		*(float*)(&属性值) = ffff;
		属性值 += 4;
		属性值 ^= g密钥常量;
		Api_WriteProcMemory(pid, 找到指针, (ULONG64)(&属性值), 4, 0);
		return;
	}
	return;
}


void ShowSkill(ULONG64 pid,const char * 要展示的技能名,ULONG64 要展示的属性索引) {
	ULONG64 人物指针 = 0;
	ULONG64 技能指针 = 0;
	ULONG32 技能判断 = 0;
	ULONG64 技能开始 = 0;
	ULONG64 技能结束 = 0;

	Api_ReadProcMemory(pid, g人物基址, (ULONG64)(&人物指针), 8, 0);//取人物指针
	Api_ReadProcMemory(pid, 人物指针 + g技能栏位, (ULONG64)(&技能指针), 8, 0);//取技能指针
	Api_ReadProcMemory(pid, 人物指针 + g技能判断, (ULONG64)(&技能判断), 4, 0);//取技能判断
	Api_ReadProcMemory(pid, 技能指针 + 技能判断 * 40 + g技能偏移, (ULONG64)(&技能开始), 8, 0);//取技能开始
	Api_ReadProcMemory(pid, 技能指针 + 技能判断 * 40 + g技能偏移 + 8, (ULONG64)(&技能结束), 8, 0);//取技能结束

	for (ULONG64 i = 0; i < (技能结束 - 技能开始) / 8; i++)
	{
		技能指针 = 0;
		Api_ReadProcMemory(pid, 技能开始 + i * 8, (ULONG64)(&技能指针), 8, 0);

		if (!技能指针)
		{
			continue;
		}

		ULONG64 temp = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能名称, (ULONG64)(&temp), 8, 0);

		//取技能名
		char arr[250] = { 0 };
		Api_ReadProcMemory(pid, temp, (ULONG64)(&(arr[0])), 250, 0);
		char 技能名称[250] = { 0 };
		WideCharToMultiByte(CP_ACP, 0, (LPWSTR)arr, 250 / 2, 技能名称, 250 / 2, 0, 0);

		if (strcmp(要展示的技能名, 技能名称) != 0)
		{
			continue;
		}
		//当前技能等级
		ULONG64 skilllevel = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能等级, (ULONG64)(&skilllevel), 8, 0);
		skilllevel ^= g密钥常量;
		skilllevel -= 4;

		ULONG64 属性数量 = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能属性 + 8, (ULONG64)(&属性数量), 8, 0);

		ULONG64 属性指针 = 0;
		Api_ReadProcMemory(pid, 技能指针 + g技能属性, (ULONG64)(&属性指针), 8, 0);

		ULONG64 当前指针 = 0;
		ULONG64 找到指针 = 0;
		Api_ReadProcMemory(pid, 属性指针 + 8, (ULONG64)(&当前指针), 8, 0);
		UCHAR sign = 1;
		Api_ReadProcMemory(pid, 当前指针 + 71, (ULONG64)(&sign), 1, 0);
		while (sign == 0)
		{
			ULONG32 当前编号 = 0;
			Api_ReadProcMemory(pid, 当前指针 + 32, (ULONG64)(&当前编号), 4, 0);
			if (当前编号 == 要展示的属性索引)
			{
				找到指针 = 当前指针;
				break;
			}
			if (当前编号 > 要展示的属性索引)
			{
				Api_ReadProcMemory(pid, 当前指针, (ULONG64)(&当前指针), 8, 0);
			}
			else {
				Api_ReadProcMemory(pid, 当前指针 + 8 * 2, (ULONG64)(&当前指针), 8, 0);
			}
		}
		if (找到指针 == 0)
		{
			return;
		}

		Api_ReadProcMemory(pid, 找到指针 + 48, (ULONG64)(&找到指针), 8, 0);
		找到指针 += ((ULONG32)(skilllevel)) * 8 - 8;

		ULONG32 属性值 = 0;
		Api_ReadProcMemory(pid, 找到指针, (ULONG64)(&属性值), 4, 0);
		属性值 ^= g密钥常量;
		属性值 -= 4;
		float ffff = *(float*)(&属性值);


		printf("【%s】的第【%d】个属性值为：%f\r\n", 技能名称, 要展示的属性索引, ffff);
		return;
	}
	return;
}

int main(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nShowCmd)
{
	//const char * iniPath = "C:\\Users\\10613\\Desktop\\1343725241\\config.ini";
	const char * iniPath = "C:\\config.ini";
	ULONG32 ret = Api_LoadDriver("");
	printf("Api_LoadDriver: 0x%08X\r\n", ret);

	ULONG64 pid = 0;
	ret = Api_GetPidByName((char*)"DNF.exe", (ULONG64)&pid);
	printf("Api_GetPidByName: 0x%08X      pid = %d \r\n", ret, pid);


	while (true)
	{
		char namearr[0x10000] = { 0 };
		GetPrivateProfileSectionNamesA(namearr, 0x10000, iniPath);
		char* nowName = namearr;
		while (strlen(nowName) != 0)
		{
			int nocd = GetPrivateProfileIntA(nowName, "无冷却", 0, iniPath);
			int maxlv = GetPrivateProfileIntA(nowName, "满级", 0, iniPath);
			for (size_t i = 0; i < 20; i++)
			{
				char attrName[20] = { 0 };
				sprintf(attrName, "属性%d", i);
				int attrVal = GetPrivateProfileIntA(nowName, attrName, -1, iniPath);
				if (attrVal == -1)
				{
					continue;
				}
				ChangeSkill(pid, nowName, i, (float)attrVal, nocd, maxlv);
			}
			nowName += strlen(nowName) + 1;
		}
		Sleep(1);
	}
	system("pause");
	return 1;
}
